package file

import (
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"chainmaker.org/chainmaker/smarteditor/conf"
	"chainmaker.org/chainmaker/smarteditor/util"

	"github.com/88250/gulu"

	"chainmaker.org/chainmaker/smarteditor/event"
	"chainmaker.org/chainmaker/smarteditor/session"
)

// RenameFileHandler handles request of renaming file or directory.
func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
	uid, err := session.GetUidFromSession(r)
	if err != nil {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	args, err := util.ReadArgs(r.Body)
	if err != nil {
		log.Errorf("rename file. decode args error. uid:%s, err: %v", uid, err)
		http.Error(w, "Forbidden", http.StatusBadRequest)
		return
	}

	oldPath := args["oldPath"].(string)
	newPath := args["newPath"].(string)
	sid := args["sid"].(string)
	if util.AnyEmpty(oldPath, newPath, sid) {
		http.Error(w, "Forbidden", http.StatusBadRequest)
		return
	}
	if oldPath == newPath {
		http.Error(w, "Forbidden", http.StatusBadRequest)
		return
	}
	if util.FileExists(newPath) {
		http.Error(w, "Forbidden", http.StatusBadRequest)
		return
	}
	if !util.FileExists(oldPath) {
		http.Error(w, "Forbidden", http.StatusBadRequest)
		return
	}
	if !session.CanAccess(uid, oldPath) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
	if !session.CanAccess(uid, newPath) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	wSession := session.WideSessions.Get(sid)
	if wSession == nil {
		log.Errorf("rename  get sid %s found no wSession", sid)
		result.Code = -1
		result.Msg = sid + " get no wSession"
		return
	}
	user := conf.GetUser(uid)
	if renameFile(oldPath, newPath) {
		AddRenameFileEventForDarwinOS(oldPath, newPath, sid)
		if util.IsContractRootDirectory(user.Workspace, oldPath) {
			oldContractName := strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(oldPath, conf.GetSrcDir(user.Workspace)), "/"), "/")
			newContractName := strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(newPath, conf.GetSrcDir(user.Workspace)), "/"), "/")
			conf.RenameContract(oldContractName, newContractName, uid)
		}
		log.Debugf("rename file. uid:%s, old file: %s, new file: [%s]", wSession.UserID, oldPath, newPath)
	} else {
		result.Code = -1
		wSession.EventQueue.Queue <- &event.Event{
			Code: event.EvtCodeServerInternalError,
			Sid:  sid,
			Data: "can't rename file " + oldPath,
		}
		return
	}
}

// renameFile renames (moves) a file from the specified old path to the specified new path.
func renameFile(oldPath, newPath string) bool {
	if err := os.Rename(oldPath, newPath); nil != err {
		log.Errorf("Renames [%s] failed: [%s]", oldPath, err.Error())
		return false
	}
	log.Debugf("Renamed [%s] to [%s]", oldPath, newPath)
	return true
}

func AddRenameFileEventForDarwinOS(oldPath, newPath, sid string) {
	//isDirectory := gulu.File.IsDir(oldPath)
	ch, err := session.GetSessionWS(sid)
	if err != nil {
		log.Warnf("get ws socker failed, err:%v", err)
		return
	}
	path := oldPath
	dir := filepath.Base(path)
	cmd := map[string]interface{}{"path": newPath, "newPath": newPath, "dir": dir, "cmd": "rename-file", "type": ""}
	err = ch.WriteJSON(&cmd)
	if err != nil {
		log.Warnf("rename file write rename event to socket failed, err:%v", err)
	}
	// if isDirectory && runtime.GOOS == "darwin" {
	// 	ch, err := session.GetSessionWS(sid)
	// 	if err != nil {
	// 		log.Warnf("get ws socker failed, err:%v", err)
	// 		return
	// 	}
	// 	path := oldPath
	// 	dir := filepath.Base(path)
	// 	cmd := map[string]interface{}{"path": newPath, "newPath": newPath, "dir": dir, "cmd": "rename-file", "type": ""}
	// 	err = ch.WriteJSON(&cmd)
	// 	if err != nil {
	// 		log.Warnf("rename file write rename event to socket failed, err:%v", err)
	// 	}
	// }
}
